﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using NetCoreCMS.Common;
using NetCoreCMS.IServices;
using NetCoreCMS.Models;
using Newtonsoft.Json;
using StackExchange.Redis;

namespace NetCoreCMS.Web.Areas.Web.Controllers
{
    public class ShopController : BaseController
    {
        public IShopService _shop { get; set; }
        public IShop_categoryService _shop_category { get; set; }
        int page = 1000;
        public IUser_oauth_appService _user_oauth_app { get; set; }
        public IActionResult Index(int id=0)
        {
            var user = GetUserInfo();
            double longitude = 116.5484941006d;
            double latitude = 31.7575372817d;
            if (user != null)
            {
                if (user.longitude + user.latitude > 0)
                {
                    longitude = user.longitude;
                    latitude = user.latitude;
                }
            }
            string LONGITUDE = HttpContext.Request.Cookies[CMSKeys.LONGITUDE];
            string LATITUDE = HttpContext.Request.Cookies[CMSKeys.LATITUDE];
            if(!string.IsNullOrEmpty(LONGITUDE)&&!string.IsNullOrEmpty(LATITUDE))
            {
                longitude = Convert.ToDouble(LONGITUDE);
                latitude = Convert.ToDouble(LATITUDE);
            }
            string redisName = Request.Host.Host.ToLower().Replace(".", "_") + "_";
            GeoRadiusResult[] shops = GetGEO(longitude, latitude, 2000, page, id);
            List<DTO.IndexShopModel> listshop = new List<DTO.IndexShopModel>();
            if (shops.Length > 0)
            {
                foreach (var item in shops)
                {
                    listshop.Add(new DTO.IndexShopModel { Distance = double.Parse(item.Distance.ToString()), Shop = _shop.GetModel(Convert.ToInt32(item.Member.ToString().Replace(redisName + "shopgeo_", ""))) });
                }
            }
            if (id > 0)
                listshop = listshop.Where(a => a.Shop.category_id == id).ToList();
            var cate = _shop_category.GetModel(id);
            if(cate==null)
            {
                cate = new Shop_category();
            }
            ViewBag.cate = cate;
            return View(listshop);
        }
        public IActionResult Show(int id)
        {
            var user = GetUserInfo();
            double longitude = 116.5484941006d;
            double latitude = 31.7575372817d;
            if (user != null)
            {
                if (user.longitude + user.latitude > 0)
                {
                    longitude = user.longitude;
                    latitude = user.latitude;
                }
            }
            string LONGITUDE = HttpContext.Request.Cookies[CMSKeys.LONGITUDE];
            string LATITUDE = HttpContext.Request.Cookies[CMSKeys.LATITUDE];
            if (!string.IsNullOrEmpty(LONGITUDE) && !string.IsNullOrEmpty(LATITUDE))
            {
                longitude = Convert.ToDouble(LONGITUDE);
                latitude = Convert.ToDouble(LATITUDE);
            }
            string redisName = Request.Host.Host.ToLower().Replace(".", "_") + "_";
            GeoRadiusResult[] shops = GetGEO(longitude, latitude, 2000, 100);
            List<DTO.IndexShopModel> listshop = new List<DTO.IndexShopModel>();
            if (shops.Length > 0)
            {
                foreach (var item in shops)
                {
                    listshop.Add(new DTO.IndexShopModel { Distance = double.Parse(item.Distance.ToString()), Shop = _shop.GetModel(Convert.ToInt32(item.Member.ToString().Replace(redisName + "shopgeo_", ""))) });
                }
            }
            var shop = listshop.FirstOrDefault(a => a.Shop.id == id);
            #region wx
            var app = _user_oauth_app.GetFirst();
            string shareUrl = config.weburl + Request.PathBase + Request.Path + Request.QueryString;
            var acmodel = WXTokenHelper.GetAccessToken(redisName, app, shareUrl);
            ViewBag.appid = app.oauth_app_id;
            ViewBag.ts = acmodel.ts;
            ViewBag.noncestr = acmodel.noncestr;
            ViewBag.jsapi_ticket = acmodel.jsapi_ticket;
            ViewBag.signature = acmodel.signature;
            ViewBag.shareUrl = shareUrl;
            #endregion
            return View(shop);
        }
        private List<Shop> GetAll(int cid = 0)
        {
            string redisName = Request.Host.Host.ToLower().Replace(".", "_") + "_";
            using (ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost:6379"))
            {
                IDatabase db = redis.GetDatabase();
                string json = db.StringGet(redisName + "shopgeo");
                if (!string.IsNullOrEmpty(json)&&json!="[]")//不为空 开始反序列化
                {
                    try
                    {
                        List<Shop> config = JsonConvert.DeserializeObject<List<Shop>>(json);
                        if (cid > 0)
                            config = config.Where(a => a.category_id == cid).ToList();
                        return config;
                    }
                    catch (Exception)//反序失败就查
                    {
                        string strwhere = "where is_pass=1 and is_lock=0";
                        if (cid > 0)
                            strwhere = strwhere + " and category_id=" + cid;
                        List<Shop> config = _shop.GetList(1, 10000, strwhere, "sort_id desc,id desc");
                        json = JsonConvert.SerializeObject(config);
                        db.StringSet(redisName + "shopgeo", json, new TimeSpan(7200 * TimeSpan.TicksPerSecond));
                        //更新geo
                        for (int i = 0; i < config.Count; i++)
                        {
                            db.GeoRemove(redisName + "location", redisName + "shopgeo_" + config[i].id);
                            db.GeoAdd(redisName + "location", config[i].longitude, config[i].latitude, redisName + "shopgeo_" + config[i].id);
                        }
                        if (cid > 0)
                            config = config.Where(a => a.category_id == cid).ToList();
                        return config;
                    }
                }
                else//为空，查，序列化,存;
                {
                    string strwhere = "where is_pass=1 and is_lock=0";
                    if (cid > 0)
                        strwhere = strwhere + " and category_id=" + cid;
                    List<Shop> config = _shop.GetList(1, 10000, strwhere, "sort_id desc,id desc");
                    json = JsonConvert.SerializeObject(config);
                    db.StringSet(redisName + "shopgeo", json, new TimeSpan(7200 * TimeSpan.TicksPerSecond));
                    //更新geo
                    for (int i = 0; i < config.Count; i++)
                    {
                        db.GeoRemove(redisName + "location", "shopgeo_" + config[i].id);
                        db.GeoAdd(redisName + "location", config[i].longitude, config[i].latitude, redisName + "shopgeo_" + config[i].id);
                    }
                    if (cid > 0)
                        config = config.Where(a => a.category_id == cid).ToList();
                    return config;
                }
            }
        }
        /// <summary>
        /// 根据我的位置查出附近的商家(腾讯高德：31.7575372817,116.5484941006)
        /// </summary>
        /// <param name="longitude">我的经度</param>
        /// <param name="latitude">我的纬度</param>
        /// <param name="distance">距离之内</param>
        /// <param name="count">最大数量</param>
        /// <returns></returns>
        private GeoRadiusResult[] GetGEO(double longitude, double latitude, double distance, int count, int cid = 0)
        {
            string redisName = Request.Host.Host.ToLower().Replace(".", "_") + "_";
            List<Shop> list = new List<Shop>();
            using (ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost:6379"))
            {
                var all = GetAll(cid);
                IDatabase db = redis.GetDatabase();
                var result = db.GeoRadius(redisName + "location", longitude, latitude, distance, GeoUnit.Kilometers, count, null, GeoRadiusOptions.WithDistance);
                return result;
            }
        }
    }
}